package com.mycompany.chatapp;

import com.mycompany.chatapp.Databaseacces.ImpDBAction;
import com.mycompany.chatapp.Databaseacces.ImpDBActionResult;
import com.mycompany.chatapp.Databaseacces.User;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.apache.log4j.Logger;
import org.jivesoftware.smackx.filetransfer.FileTransferManager;
import org.jivesoftware.smackx.filetransfer.FileTransferListener;
import org.jivesoftware.smackx.filetransfer.FileTransferRequest;
import org.jivesoftware.smackx.filetransfer.FileTransferNegotiator;
import org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer;
import org.jivesoftware.smackx.filetransfer.IncomingFileTransfer;
import org.jivesoftware.smackx.ServiceDiscoveryManager;


/**
 * This Class Creates the functionalities of InstantMessage.
 * @author Group C
 */
public class ImpInstantMessage implements InstantMessage
{
   //Create a XMMP conection to server XMPP
   private XMPPConnection connection=null;
   private static ImpInstantMessage instantMessage=null;
   private PacketFilter filter = null; 
   private MultiUserChat chat = null;
   private PacketListener listen=null;
   ServiceDiscoveryManager servicemanager=null;
   private Map hm = null;
   //Logger for ImpInstantMessage
   private final static Logger log = Logger.getLogger(ImpInstantMessage.class);
   int numberOfMessages=0;
   int numberOfContacts=0;
   boolean sendBoolean;
   boolean sendUserContentOK=false;
   boolean fileReceiverOK=false;
   com.mycompany.chatapp.Databaseacces.ImpDBManager dbmanager;
    /**
     * Contructor of InstantMessage class
     */
    private ImpInstantMessage()
    {
        hm= new HashMap();
        this.addHash();
        dbmanager = com.mycompany.chatapp.Databaseacces.ImpDBManager.getInstanceManager();
    }

    /**
     * This method follows the Singleton Patern, ensure only one instance and 
     * provide a global point of acces to that instance.
     * @return instantMessage
     */
    public static synchronized ImpInstantMessage getIntanceMessage()
    {
      if(instantMessage==null)
       {
           instantMessage=new ImpInstantMessage();
       }
       return instantMessage;
    }
    /**
     * This method create a login conection in the personal count of XMPP googleTalk
     * @param userName
     * @param password
     * @throws XMPPException 
     * 
     */
    public boolean login(String userName, String password) 
    {
       ConnectionConfiguration config=new ConnectionConfiguration("talk.google.com",5222,"gmail.com");
       config.setSASLAuthenticationEnabled(true);
       config.setReconnectionAllowed(true);
       boolean loginOK=false;

       // if(!registered(userName+"@gmail.com")){

       try {
            connection=new XMPPConnection(config);
            connection.connect();
            connection.login(userName+"@gmail.com", password);
            
            
            filter = new PacketTypeFilter(Message.class);
            listen = (PacketListener) new ImpListener(instantMessage);

            connection.addPacketListener(listen,filter);
            chat = new MultiUserChat(connection, "Search");   

            //Shows the user connection in the XMMP systmem
            if(log.isDebugEnabled())
                log.info("You are connected as: "+connection.getUser());
            loginOK =true;
        } catch (XMPPException ex) {
            loginOK=false;
            java.util.logging.Logger.getLogger(ImpInstantMessage.class.getName()).log(Level.SEVERE, null, ex);
        }

       //loginOK=false;
        //}
           return loginOK;
   }

     /**
     * Disconect the XMPP user
     */
    public void logout()
    {
        if(connection!=null)
        {
            if(log.isDebugEnabled())
                log.info("User "+connection.getUser()+" has finished the session!!!");
            
            connection.disconnect();
        }
    }
    /**
     * This method create a chat to specific person and send the message 
     * @param message to send
     * @param to is a contact 
     * @throws XMPPException 
     */
    public void sendMessageSearchProfile(String Content, String to, int type) 
    { 
       System.out.println("Content");
        Roster roster = connection.getRoster();
        Collection<RosterEntry> entries = roster.getEntries();
      
         for (RosterEntry r : entries) 
        {     
            Message msg = new Message();
            ImpSearchProfile searchProfile= new ImpSearchProfile(Content, to, connection.getUser(),type);
            msg.setTo(r.getUser()); 
      
            msg.setProperty("Type", searchProfile);
        
            try {
                chat.sendMessage(msg);
                 numberOfMessages++;
                 
            } catch (XMPPException ex) {
                
                if(log.isDebugEnabled())
                    log.warn("Client cannot send the SearchProfile Message");
            }
        }
    }
    
     /**
     * This method send a SearchResult message to other gtalk users
     * @param result
     * @param to 
     */
    public void sendMessageSearchResult(ImpSearchResult result, String to) 
    {   
        Message msg = new Message();
        msg.setTo(to); 
        msg.setProperty("Type", result);
        
        try {
            chat.sendMessage(msg);
        } catch (XMPPException ex) {
            
            if(log.isDebugEnabled())
               log.warn("Client cannot send the SearchResult Message"); 
        }
    }
    
    /**
     * This method send a SearchUserContent to ohters gtalk users.
     * @param IDUser
     * @param addressUser
     * @param URLContent
     * @param to 
     */
    public void sendMessageUserContent(String IDUser, String addressUser, String URLContent, String to) 
    {   
        
        Message msg = new Message();
        String myPath=System.getProperty("user.home");
        ImpUserContent userContent= new ImpUserContent(IDUser, addressUser, URLContent, null, to);
        msg.setTo(to);
        msg.setProperty("Type", userContent);
        
        try
        {
            chat.sendMessage(msg); //Send the message UserContent
            sendUserContentOK=true;
  
            String temp=URLContent.substring(0, 1); 
            
            //si es windows, hace esto
            if(temp.equals("C") || temp.equals("c") == true)
            { 
                String delimiter="\\";
                System.out.println("el addressUser es"+URLContent);
                String[] temp2 = URLContent.split(delimiter);
                int ln=temp2.length;
                String namePhoto=temp2[ln-1];
                this.fileReceiver(myPath+"\\"+namePhoto);
            }   
            //si el SO es windows hace esto.
            else
            { 
                String delimiter="\\/";
                System.out.println("el addressUser es"+URLContent);
                String[] temp2 = URLContent.split(delimiter);
                int ln=temp2.length;
                String namePhoto=temp2[ln-1];
                this.fileReceiver(myPath+"/"+namePhoto);
            }
            
            fileReceiverOK=true;
          
        } catch (XMPPException ex) {
            
            if(log.isDebugEnabled())
                log.warn("Client cannot send the UserContent Message");
        }
    }
    
    /**
     * This method obtain and show a contact list of the XMPP user
     */
    public void displayContactList()
    {
        //Obtain a conctact list in this conection
        Roster roster = connection.getRoster();
        Collection<RosterEntry> entries = roster.getEntries();
        
        //Print message "Contact List"
         if(log.isDebugEnabled())
             log.info("\n\n" + entries.size() + " Contact list: ");
         
        //Print a contact list 
        for (RosterEntry r : entries) 
        {
            numberOfContacts++;
            
            if(log.isDebugEnabled())
                log.info("User: "+r.getUser());
        }
    }
    
    /**
     * This method return the status of user
     * @return true 
     */
    public boolean isConnect(){
        
        if(this.connection.isConnected()) return true;
        else return false;
    }
    
    /**
     * This method return if the specific content is in the local HashMap
     * @param content
     * @return 
     */
    public boolean searchContent(String content)
    { 
        System.out.println(hm.toString());
        System.out.println(content);
         System.out.println(hm.containsKey(content));
       if(hm.containsKey(content))
           return true;
               
        return false;
    }
    
    /**
     * This method search in the local HashMap and return a List of Contents
     * @param id
     * @return ArrayList of results 
     */
    public ArrayList <ImpContent> getContent(String id)
    {
        ArrayList <ImpContent> result = new ArrayList<ImpContent>();
        ImpContent contenido = new ImpContent();
                
        String name = (String) hm.get(id);
        System.out.println("hjhjhjhh"+name);
        
        contenido.setNamePhoto(name);
        result.add(0,contenido );
        
        return result;
    }
    
    /**
     * This method add to local HashMap values
     */
    public void addHash()
    {
        this.hm.put("leon","Africa.jpg");
        this.hm.put("ballena","Viaje.jpg");
        
    }
    
    /**
     * This method transfer a file to other gtalk user/s.
     * @param fileName
     * @param destination
     * @throws XMPPException 
     */
    public void fileTransfer(String fileName, String destination) throws XMPPException
    {
        sendBoolean=false;
        // Create the file transfer manager
        FileTransferManager manager = new FileTransferManager(connection);
        // Create the outgoing file transfer
        OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(destination);
       
        // Send the file
        try 
        {
            transfer.sendFile(new File(fileName), "Sending the file");
            sendBoolean = true;
            while(!transfer.isDone())
            {
                if(log.isDebugEnabled())
                    log.info(transfer.getProgress() + " is done!");

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    if(log.isDebugEnabled())
                        log.info("No funciona el Thread");
                }
            }
            if(log.isDebugEnabled())
                log.info("The File transfer has finished!!");

          } catch (XMPPException e) {
              
              if(log.isDebugEnabled())
                  log.error("File can't be transferred");
          }
    }
    
    /**
     * This method receive and incoming file for other gtalk user
     * @param fileName
     * @throws XMPPException 
     */
    public void fileReceiver(final String fileName) throws XMPPException
    {
        log.info("dentro de fileReceiver");
        // Create the file transfer manager
        final FileTransferManager manager = new FileTransferManager(connection);
        FileTransferNegotiator.setServiceEnabled(connection,true);
        
        // Create the listener
        manager.addFileTransferListener(new FileTransferListener() {
              public void fileTransferRequest(FileTransferRequest request) {
                  // Accept it
                   try {
                            IncomingFileTransfer transfer = request.accept();
                            transfer.recieveFile(new File(fileName));
                            
                            if(log.isDebugEnabled())
                                log.info("File Received!!");
          
                   } catch (XMPPException e) {

                        if(log.isDebugEnabled())
                            log.info("File can't be received!");
                   }
              }
        });
    }
    
    /**
     * This method return the connection of this.user!
     * @return connection.
     */
    public XMPPConnection getXMPPConnection()
    {
        return this.connection;
    }
}

